# -*- coding: utf-8 -*-
# @Time : 2022/5/19 11:27
# @Author : Dftre
# @Email : 3066417822@qq.com
# @File : generator.py
# @Project : 代码生成器
# @Version : 1.3.2
# @LastTime : 2022/5/31 11:31
import re
from processor import Interpolation, Estimate, ErgodicLine, Objects, Circulation


class GeneratorException(Exception):
    InterpolationError = 'InterpolationError'
    EstimateError = 'EstimateError'

    def __init__(self, ExceptionCode, ExceptionLine):
        msg = {
            'InterpolationError': '判断语法错误！错误位于第{}行',
            'EstimateError': '插值语法错误！错误位于第{}行',
        }
        self.msg = msg[ExceptionCode].format(ExceptionLine)

    def __str__(self):
        return self.msg


class Generator:
    def __init__(self):
        self.val_dict = {}  # 变量表
        self.if_list = []  # 真值表
        self.line_dict = {}  # 遍历变量表
        self.objects_dict = {}  # 对象表
        self.class_dict = {}  # 类表
        self.test = ''  # 翻译后的内容

    def __str__(self):
        return (
                'val_dict={}\nif_list={}\nline_dict={}\n' +
                'objects_dict={}\nclass_dict={}'
        ).format(
            self.val_dict,
            self.if_list,
            self.line_dict,
            self.objects_dict,
            self.class_dict,
        )

    # 清理变量
    def clear(self):
        self.val_dict = {}
        self.if_list = []
        self.line_dict = {}
        self.objects_dict = {}
        self.test = ''

    # 将一个变量添加到变量表中
    def add_val(self, val_name: str, val):
        self.val_dict[val_name] = str(val)

    # 将一个字典对象转换添加到变量表中
    def add_val_dict(self, dictVal: dict):
        for i in dictVal:
            self.val_dict[i] = str(dictVal[i])

    # 将一个对象添加到变量表中
    def add_val_class(self, val_name: str, val):
        for a in dir(val):
            # 处理掉私有变量
            if a.startswith('_') or a == 'metadata':
                continue
            # 获取属性的值
            v = getattr(val, a)
            # 检查是否是方法
            if callable(v):
                continue
            self.val_dict[val_name + '.' + a] = str(getattr(val, a))

    # 将一个字符串添加到真值表中
    def add_if(self, string: str):
        self.if_list.append(re.sub(r'\s', '', string))

    # 将一个字符串列表中的字符串添加到真值表中
    def add_if_list(self, stringList: list):
        for i in stringList:
            if len(str(i)) != 0:
                self.add_if(i)

    # 添加一个遍历列表变量
    def add_line(self, val_name: str, val: list):
        self.line_dict[val_name] = val

    # 添加一个对象到对象表
    def add_object(self, object_name: str, object_val: dict):
        self.objects_dict[object_name] = object_val

    # 添加一个py对象到对象表
    def add_object_object(self, object_name: str, object_val):
        for a in dir(object_val):
            # 处理掉私有变量
            if a.startswith('_') or a == 'metadata':
                continue
            # 获取属性的值
            v = getattr(object_val, a)
            # 检查是否是方法
            if callable(v):
                continue
            self.objects_dict[object_name] = str(getattr(object_val, a))

    # 往一个类里添加一个对象
    def add_class(self, class_name: str, object_val):
        object_dict = {}
        for a in dir(object_val):
            # 处理掉私有变量
            if a.startswith('_') or a == 'metadata':
                continue
            # 获取属性的值
            v = getattr(object_val, a)
            # 检查是否是方法
            if callable(v):
                continue
            object_dict[a] = str(getattr(object_val, a))
        try:
            self.class_dict[class_name].append(object_dict)
        except:
            self.class_dict[class_name] = [object_dict]

    # 往一个类里添加一个对象
    def add_class_dict(self, class_name: str, dict_val):
        try:
            self.class_dict[class_name].append(dict_val)
        except:
            self.class_dict[class_name] = [dict_val]

    # 开始编译
    def start(self, template: str):
        _text_list = template.split('\n')
        text_list = []
        _text = []
        flag = 0
        for line, text in enumerate(_text_list):
            if '---' in text:
                flag = 1
                _text = []
            elif '+++' == text:
                flag = 0
                text_list.append('\n'.join(_text)+'\n')
            elif flag == 1:
                _text.append(text)
            else:
                text_list.append(text)

        for line, text in enumerate(text_list):
            # 处理 ~{} 判断语法
            text_list[line] = Estimate(self.if_list).sub(text_list[line])
            if not text_list[line]:
                continue
            # 处理 #{} 插值语法
            text_list[line] = Interpolation(self.val_dict).sub(text_list[line])

            text_list[line] += '\n'
            # 处理 -{} 遍历语法
            text_list[line] = ErgodicLine(self.line_dict).sub(text_list[line])
            # 处理 ${} 对象语法
            text_list[line] = Objects(self.objects_dict).sub(text_list[line])
            # 处理 @{} 对象语法
            text_list[line] = Circulation(self.class_dict).sub(text_list[line])

        return ''.join(text_list)
